package yolo

import (
	"appengine"
	"appengine/taskqueue"
	"time"
)

type PostParams map[string][]string

func mayPostTask(c appengine.Context, url string, qname string, params PostParams, max int) (bool, error) {

	counter := &Counter{url + "-queue-cnt"}
	if v, _ := counter.Increment(c); v > max {
		counter.Decrement(c)
		return false, nil
	}

	t := taskqueue.NewPOSTTask(url, (map[string][]string)(params))
	if _, err := taskqueue.Add(c, t, qname); err != nil {
		c.Errorf("taskqueue.Add failed: %s", err.Error())
		return false, err
	}

	return true, nil
}

func mayPostTaskWithDelay(c appengine.Context, url, qname string, delay time.Duration, params PostParams, max int) (bool, error) {

	counter := &Counter{url + "-queue-cnt"}
	if v, _ := counter.Increment(c); v > max {
		counter.Decrement(c)
		return false, nil
	}

	t := taskqueue.NewPOSTTask(url, (map[string][]string)(params))
	t.Delay = delay
	if _, err := taskqueue.Add(c, t, qname); err != nil {
		c.Errorf("taskqueue.Add failed: %s", err.Error())
		return false, err
	}

	return true, nil
}

func postTask(c appengine.Context, url string, qname string, params PostParams) (bool, error) {
	t := taskqueue.NewPOSTTask(url, (map[string][]string)(params))
	if _, err := taskqueue.Add(c, t, qname); err != nil {
		c.Errorf("taskqueue.Add failed: %s", err.Error())
		return false, err
	}
	return true, nil
}

func postTaskWithDelay(c appengine.Context, url string, qname string, delay time.Duration, params PostParams) (bool, error) {
	t := taskqueue.NewPOSTTask(url, (map[string][]string)(params))
	t.Delay = delay
	if _, err := taskqueue.Add(c, t, qname); err != nil {
		c.Errorf("taskqueue.Add failed: %s", err.Error())
		return false, err
	}
	return true, nil
}

func markTaskStarted(c appengine.Context, url string) {
	counter := &Counter{url + "-queue-cnt"}
	counter.Decrement(c)
}

func mayRunTask(c appengine.Context, taskKey string, maxConcurrentTask int, f func() error) error {
	counter := &Counter{taskKey}
	if err := counter.TryIncrement(c, (maxConcurrentTask - 1)); err != nil {
		return err
	}
	defer func() {
		if ret, _ := counter.Decrement(c); ret == 0 {
			counter.Delete(c)
		}
	}()

	return f()
}
